# Origin: http://djangosnippets.org/snippets/1478/
from django.db                    import models
from django.core.serializers.json import DjangoJSONEncoder
from django.utils                 import simplejson as json

class JSONDictField(models.TextField):
    """JSONDictField is a generic textfield that neatly serializes/unserializes
    JSON objects seamlessly"""

    # Used so to_python() is called
    __metaclass__ = models.SubfieldBase

    def to_python(self,value):
        """Convert our string value to JSON after we load it from the DB"""
        if value in ("",None):
            return None
        if isinstance(value, basestring):
            return json.loads(value)
        return value

    def get_db_prep_save(self,value):
        """Convert our JSON object to a string before we save"""
        if value in ("",None):
            return None
        if isinstance(value,basestring):
            value = self.to_python(value)
        if isinstance(value,dict):
            value = json.dumps(value,cls=DjangoJSONEncoder)
        else:
            raise ValueError,"must be a dict"
        return super(JSONDictField,self).get_db_prep_save(value)

class JSONListField(models.TextField):
    """JSONListField is a generic textfield that neatly serializes/unserializes
    JSON objects seamlessly"""

    # Used so to_python() is called
    __metaclass__ = models.SubfieldBase

    def to_python(self, value):
        """Convert our string value to JSON after we load it from the DB"""
        if value in ("",None):
            return None
        if isinstance(value, basestring):
            return json.loads(value)
        return value

    def get_db_prep_save(self,value):
        """Convert our JSON object to a string before we save"""
        if value in ("",None):
            return None
        if isinstance(value,basestring):
            value = self.to_python(value)
        if isinstance(value,(tuple,list)):
            value = json.dumps(value,cls=DjangoJSONEncoder)
        else:
            raise ValueError,"must be a list or tuple"
        return super(JSONListField,self).get_db_prep_save(value)

